﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

using KSOAdmin.Core;
using KSOAdmin.Core.EFDbContext;
using KSOAdmin.Core.Expressions;
using KSOAdmin.IRepository;
using KSOAdmin.IServices;
using KSOAdmin.Models.Core;
using KSOAdmin.Models.DomainModels.System;
using KSOAdmin.Models.MapperModels;
using KSOAdmin.Models.MapperModels.Enums;
using KSOAdmin.Models.MapperModels.Page;

using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;

using StackExchange.Redis;

namespace KSOAdmin.Services
{
    public abstract class BasicServices<TModel> : IDependency, IBasicServices<TModel> where TModel : class, new()
    {
        protected IBasicRepository<TModel> repository { get; set; }
        private ResponseModel<TModel> Response { get; set; }
        /// <summary>
        /// 文件大小  KB
        /// </summary>
        private int FileSize { get; set; } = 4 * 1024 * 1024;
        public BasicServices()
        {
            Response = new ResponseModel<TModel>();
        }
        public Microsoft.AspNetCore.Http.HttpContext Context
        {
            get
            {
                return Core.Other.KSOHttpContext.Current;
            }
        }

        #region 查询
        public TModel FindFirst(Expression<Func<TModel, bool>> expression)
        {
            return repository.FindFirst(expression);
        }

        public async Task<TModel> FindFirstAsync(Expression<Func<TModel, bool>> expression)
        {
            return await repository.FindFirstAsync(expression);
        }

        public async Task<List<TModel>> FindListAsync(Expression<Func<TModel, bool>> expression =null, Expression<Func<TModel, Dictionary<object, QueryOrderBy>>> orderBy = null, bool isTracking = true)
        {
            return await repository.FindListAsync(expression,  orderBy , isTracking);
        }

        public IQueryable<TModel> FindAsIQueryable(Expression<Func<TModel, bool>> predicate = null, Expression<Func<TModel, Dictionary<object, QueryOrderBy>>> orderBy = null, bool isTracking = true)
        {
            return repository.FindOtherIQueryable (predicate, orderBy, isTracking);
        }

        public IQueryable<T> FindOtherIQueryable<T>(Expression<Func<T, bool>> predicate = null, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBy = default, bool isTracking = true) where T : class
        {
            return repository.FindOtherIQueryable<T>(predicate, orderBy ,  isTracking);
        }

        public async Task<List<T>> FindOtherListAsync<T>(Expression<Func<T, bool>> predicate = null, bool isTracking = true) where T : class
        {
               return await repository.FindOtherListAsync<T>(predicate,  isTracking);
        }
        #endregion

        #region 分页
        public IQueryable<T> IQueryablePage<T>(out int rowcount, Expression<Func<T, bool>> predicate, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBy = null, int pageIndex = 1, int pageSize = 20) where T : class
        {
            return repository.IQueryablePage<T>(out  rowcount, predicate, orderBy,  pageIndex,  pageSize);
        }

        public IQueryable<TModel> IQueryablePage(out int rowcount, Expression<Func<TModel, bool>> predicate, Expression<Func<TModel, Dictionary<object, QueryOrderBy>>> orderBy = null, int pageIndex = 1, int pageSize = 20)
        {
            return repository.IQueryablePage(out rowcount, predicate, orderBy, pageIndex, pageSize);
        }

        public async Task<PageListModel<TModel>> PageListAsync(Expression<Func<TModel, bool>> predicate, Expression<Func<TModel, Dictionary<object, QueryOrderBy>>> orderBy = null, int pageIndex = 1, int pageSize = 20)
        {
            return await repository.PageListAsync(predicate, orderBy ,  pageIndex , pageSize);
        }

        public async Task<PageListModel<TModel>> PageListAsync(IQueryable<TModel> queryable, Expression<Func<TModel, Dictionary<object, QueryOrderBy>>> orderBy = null, int pageIndex = 1, int pageSize = 20)
        {
            return await repository.PageListAsync(queryable, orderBy, pageIndex, pageSize);
        }

        public async Task<PageListModel<T>> PageOtherListAsync<T>(IQueryable<T> queryable, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBy = null, int pageIndex = 1, int pageSize = 20) where T : class
        {
            return await repository.PageOtherListAsync(queryable, orderBy, pageIndex, pageSize);
        }

        #endregion

        #region 删 改 增加
        public async Task<ResponseModel<TModel>> Upload(List<TModel> files)
        {
            ResponseModel<TModel> response = new ResponseModel<TModel>();
            int row = await repository.UpdateRangeAsync(files);
            if (row > 0)
            {
                response.msg = "修改成功";
                response.code = 200;
            }
            else
            {
                response.msg = "修改失败";
                response.code = -1;
            }
            return response;
        }

        public async Task<ResponseModel<TModel>> Upload(TModel TModel)
        {
            ResponseModel<TModel> response = new ResponseModel<TModel>();
            int row = await repository.UpdateAsync(TModel);
            if (row > 0)
            {
                response.msg = "修改成功";
                response.code = 200;
            }
            else
            {
                response.msg = "修改失败";
                response.code = -1;
            }
            return response;
        }

        public async Task<ResponseModel<TModel>> AddEntity(TModel entity, bool validationEntity = true)
        {
            ResponseModel<TModel> response = new ResponseModel<TModel>();
            await repository.AddAsync(entity, validationEntity);
            response.msg = "添加成功";
            return response;
        }
        public async Task<ResponseModel<T>> AddEntity<T>(T entity, bool validationEntity = true) where T : class
        {
             ResponseModel<T> response = new ResponseModel<T>();
             await repository.AddAsync<T>(entity, validationEntity);
             response.msg = "添加成功";
             return response;
            throw new Exception();
        }
        public async Task<ResponseModel<TModel>> Add(List<TModel> list = null, bool validationEntity = true)
        {
            ResponseModel<TModel> response = new ResponseModel<TModel>();
            await repository.AddRangeAsync(list);

            response.msg = "添加成功";
            return response;
        }

        public async Task<ResponseModel<TModel>> Del(object[] keys, bool delList = true)
        {
            int row = await Task.Run(() =>
            {
                return repository.DeleteWithKeys(keys, delList);
            });
            return row > 0 ? ResponseModel<TModel>.Success() : ResponseModel<TModel>.Fail("执行失败");
        }

        public async Task<ResponseModel<TModel>> Del(TModel TModel, bool delList = true)
        {
            int row = await repository.DeleteAsync(TModel, delList);
            return row > 0 ? ResponseModel<TModel>.Success() : ResponseModel<TModel>.Fail("执行失败");
        }

        public async Task<ResponseModel<TModel>> Del(List<TModel> list, bool delList = true)
        {
            int row = await repository.DeleteRangeAsync(list);
            return row > 0 ? ResponseModel<TModel>.Success() : ResponseModel<TModel>.Fail("执行失败");
        }

       
        #endregion 

        #region 下载上传
        /// <summary>
        /// 下载模板
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public Task<ResponseModel > DownLoadTemplate()
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 上传，导入
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ResponseModel> Import(List<IFormFile> files)
        {
            if (files == null || files.Count == 0) return ResponseModel.Fail("请上传文件");

            var limitFiles = files.Where(x => x.Length > FileSize ).Select(s => s.FileName).Count();
            if (limitFiles > 0)
            {
                return ResponseModel.Fail($"文件大小不能超过：{FileSize} KB,{string.Join(",", limitFiles)}");
            }
            string fullPath = $"Upload/Tables/{typeof(TModel).GetEntityTableName()}/{DateTime.Now.ToString("yyyMMddHHmmsss") + new Random().Next(1000, 9999)}/";
            int i = 0;

            if (!Directory.Exists(fullPath)) Directory.CreateDirectory(fullPath);
            for (i = 0; i < files.Count; i++)
            {
                string fileName = files[i].FileName;
                using (var stream = new FileStream(fullPath + fileName, FileMode.Create))
                {
                   await files[i].CopyToAsync(stream);
                }
            }
            return ResponseModel.Success(fullPath, "文件上传成功");
        }
        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="pageData"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public Task<ResponseModel> Export(PageDataOptions pageData)
        {
            throw new NotImplementedException();
        }

        public Task<PageListModel<T>> PageOtherListAsync<T>(IQueryable<TModel> queryable, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBy = null, int pageIndex = 1, int pageSize = 20) where T : class
        {
            throw new NotImplementedException();
        }

        #endregion

    }
}
